#coding=UTF-8
import random
import urllib2, urllib
import logging
import traceback
import socket, re
import cherrypy
import datetime
import calendar

socket.setdefaulttimeout(10)

L = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

def long2str(i):
    if i == 0: return '0'
    result = []
    lenth = len(L)
    while i > 0 :
        result.insert(0, L[(i % lenth)])
        i /= lenth
    return "".join(result)

def parse(result):
    return dict(x.split(':') for x in result.split(';'))

def hex2str(s):
    '''16进制转字符串'''
    if s[:2] == '0x' or s[:2] == '0X':
        s = s[2:]
    res = ""
    for i in range(0, len(s), 2):
        hex_dig = s[i:i + 2]
        res += (chr(int(hex_dig, base=16)))
    return res


def str2hex(string):
    '''字符串转16进制'''
    res = ""
    for s in string:
        hex_dig = hex(ord(s))[2:]
        if len(hex_dig) == 1:
            hex_dig = "0" + hex_dig
        res += hex_dig
    return res

def rc4(data, key):
    x = 0
    box = range(256)
    for i in range(256):
        x = (x + box[i] + ord(key[i % len(key)])) % 256
        box[i], box[x] = box[x], box[i]
    x = 0
    y = 0
    out = []
    for char in data:
        x = (x + 1) % 256
        y = (y + box[x]) % 256
        box[x], box[y] = box[y], box[x]
        out.append(chr(ord(char) ^ box[(box[x] + box[y]) % 256]))
    return ''.join(out)

def http_get(url):
    res = '{"code":-10, "msg":"server error"}'
    try:
        logging.debug(u"请求地址: %s" % url)
        res = urllib2.urlopen(url).read()
    except:
        logging.error(u'URL:%s访问失败:' % url, exc_info=True)
    finally:
        return res

def http_post(url, data):
    try:
        f = urllib2.urlopen(url, urllib.urlencode(data))
        res = f.read()
        f.close()
        return res
    except:
        logging.error(u'URL:%s Post访问失败:%s' % (url, traceback.format_exc()))
        return '{"code":500, "msg":"server error"}'

def number_check(called):
    called = urllib.unquote(called)
    called = called.replace(" ", "").replace("-", "")
    if len(called) < 11:
        return None
    number = called 
    if called[:5] in ['12593', '12580', '17909', '17951', '17950', '10193', '17911']:
        number = called[5:]
    elif called[:4] == '0086':
        number = called[4:]
    elif called[:2] == '86':
        number = called[2:]
    elif called[:3] == '+86':
        number = called[3:]
    elif called[:3] == ' 86':
        number = called[3:]
    elif called[:2] == '00':
        #if called.isdigit():
        #    return called
        return None
    elif called[:1] == '+':
        called = '00' + called[1:]
        if called.isdigit():
            return called
        return None
    if number[:1] == '1':
        if len(number) == 11 and number.isdigit():
            return number
        return None
    elif number[:1] == '0':
        if len(number) >= 9 and len(number) <= 12 and number.isdigit():
            if number[:3] in ('010', '020', '021', '022' ,'023', '024', '025', '026', '027', '028', '029'):
                if number[3:5] in ('11', '12') or number[3] in ('0', '9'):
                    return None
            elif number[4:6] in ('11', '12') or number[4] in ('0', '9'):
                return None
            
            return number
        return None
    return None

def get_ip():
    header = cherrypy.request.headers
    ip = ''
    ipList = header.get("X-Forwarded-For", "").replace(" ", "").split(",")
    if ipList:
        #for p in ipList:
        #    if p[:2] == '10' or p[:3] in ('127', '192', '172'):
        #        continue
        #    else:
        #        ip = p
            
        ip = ipList[0]
        if len(ipList) > 1 and (ip[:2] == '10' or ip[:3] in ('127', '192', '172')):
            ip = ipList[1]
    if not ip:
        ip = header.get('X-Real-Ip')
    if not ip:
        ip = header.get('Remote-Addr')
    if not ip:
        ip = header.get('REMOTE-ADDR')
    return ip

def decrypt(pwd):
    enstr = ''
    encrypt_key = '0123456789'
    decrypt_key = '5678901234'
    if len(pwd) == 0:
        return False
    for i in range(len(pwd)):
        changed = False
        for j in range(len(decrypt_key)):
            if pwd[i] == decrypt_key[j]:
                enstr += encrypt_key[j]
                changed = True
        if not changed:
            enstr += pwd[i]
    return enstr

#检测是否是手机号 返回1：是手机号 -1：不是手机号
def is_mobile(phone):
    if re.match("^1[34578][0-9]{9}$", phone):
        return 1
    return -1

def is_valid_phone(phone):
    r1 = re.compile(r'(?:(?:0(?=1)|1(?=2)|2(?=3)|3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)){4}|(?:9(?=8)|8(?=7)|7(?=6)|6(?=5)|5(?=4)|4(?=3)|3(?=2)|2(?=1)|1(?=0)){4})\d', re.IGNORECASE)
    r2 = re.compile(r'([\d])\1{4,}', re.IGNORECASE)
    if r1.search(phone) or r2.search(phone):
        return False
    return True

##检测是否为数字返回1说明为数字，返回-1说明不全为数字
#def is_number(account):
#    no = 0
#    no = len(account)
#    if no < 5:
#        return -1
#    regex = ur'[0-9]{%d}' % no
#    if re.match(regex, account):
#        return 1
#    return -1

#密码长度校验
def check_pwd_length(pwd):
    if len(pwd) < 6 or len(pwd) > 16:
        return False
    else:
        return True


_MONTH = ((0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31),
             (0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31))

def do_date(y=0, m=0, d=0, date=None):

    if not date:
        date = datetime.datetime.now()
    if d != 0:
        date += datetime.timedelta(days=d)
    if not (y or m):
        return date.strftime("%Y-%m-%d %H:%M:%S")

    n = int(date.year) * 12 + int(date.month) - 1
    n = n + m
    ryear = n / 12
    rmonth = n % 12 + 1
    rday = date.day
    if calendar.isleap(ryear):
        if rday > _MONTH[1][rmonth]:
            rday = _MONTH[1][rmonth]

    else:
        if rday > _MONTH[0][rmonth]:
            rday = _MONTH[0][rmonth]

    y += (m + int(date.month) - 1) / 12
    result = date.replace(year=date.year + y, month=rmonth, day=rday)
    return result.strftime("%Y-%m-%d %H:%M:%S")

_UTF8_TYPES = (bytes, type(None))

def utf8(value):
    if isinstance(value, _UTF8_TYPES):
        return value
    assert isinstance(value, unicode)
    return value.encode("utf-8")

def checkIdcard(idcard):
    try:
        Errors=['验证通过!','身份证号码位数不对!','身份证号码出生日期超出范围或含有非法字符!','身份证号码校验错误!','身份证地区非法!']
        area={"11":"北京","12":"天津","13":"河北","14":"山西","15":"内蒙古","21":"辽宁","22":"吉林","23":"黑龙江","31":"上海","32":"江苏","33":"浙江","34":"安徽","35":"福建","36":"江西","37":"山东","41":"河南","42":"湖北","43":"湖南","44":"广东","45":"广西","46":"海南","50":"重庆","51":"四川","52":"贵州","53":"云南","54":"西藏","61":"陕西","62":"甘肃","63":"青海","64":"宁夏","65":"新疆","71":"台湾","81":"香港","82":"澳门","91":"国外"}
        idcard=str(idcard)
        idcard=idcard.strip()
        idcard_list=list(idcard)
        #地区校验
        if not idcard[:17].isdigit():
            return '请输入正确的身份证号'
        if(not area[(idcard)[0:2]]):
            return Errors[4]
        if(len(idcard)==18):
            #出生日期的合法性检查
            #闰年月日:((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))
            #平年月日:((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))
            if(int(idcard[6:10]) % 4 == 0 or (int(idcard[6:10]) % 100 == 0 and int(idcard[6:10])%4 == 0 )):
                ereg=re.compile('[1-9][0-9]{5}19[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}[0-9Xx]$')#//闰年出生日期的合法性正则表达式
            else:
                ereg=re.compile('[1-9][0-9]{5}19[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}[0-9Xx]$')#//平年出生日期的合法性正则表达式
            #//测试出生日期的合法性
            if(re.match(ereg,idcard)):
                #//计算校验位
                S = (int(idcard_list[0]) + int(idcard_list[10])) * 7 + (int(idcard_list[1]) + int(idcard_list[11])) * 9 + (int(idcard_list[2]) + int(idcard_list[12])) * 10 + (int(idcard_list[3]) + int(idcard_list[13])) * 5 + (int(idcard_list[4]) + int(idcard_list[14])) * 8 + (int(idcard_list[5]) + int(idcard_list[15])) * 4 + (int(idcard_list[6]) + int(idcard_list[16])) * 2 + int(idcard_list[7]) * 1 + int(idcard_list[8]) * 6 + int(idcard_list[9]) * 3
                Y = S % 11
                M = "F"
                JYM = "10X98765432"
                M = JYM[Y]#判断校验位
                if(M == idcard_list[17]):#检测ID的校验位
                    return None
                else:
                    return Errors[3]
            else:
                return Errors[2]
        else:
            return Errors[1]
    except:
        return Errors[2]

if __name__=='__main__':
    print checkIdcard('12345678901234567x')
    
